package worker

import (
	"crontab/common"
	"os/exec"
	"time"
)

//调度任务执行器
type Executor struct {
}

var (
	G_Executor *Executor
)

//执行一个任务,因为有很多任务，因此我们需要起很多协程
func (executor *Executor) ExecuteJob(executeInfo *common.JobExecuteInfo) {
	go func() {
		var (
			cmd    *exec.Cmd
			output []byte
			err    error
			result *common.JobExecutorResult
			//首先我们需要获取到一把锁--redis
			jobRdLock *common.JobRedisDistributeLock

		//	jobZkLock *common.JobZKDistributeLock
		)

		result = &common.JobExecutorResult{
			Executor: executeInfo,
			Ouput:    make([]byte, 0),
		}

		//创建一把分布式锁--redis
		jobRdLock = G_JobMgr.CreateDistributeLock(G_Config.LockPath)
		//为了防止老是一个抢到锁，我们随机睡眠一下(0-1s)
		//	time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)

		//接下来我们需要进行抢占分布式锁
		err = jobRdLock.TryLock(executeInfo.Job.Name)
		//释放锁
		defer jobRdLock.Unlock()

		//jobZkLock = G_JobMgr.CreateZKDistributeLock(executeInfo.Job.Name)
		//err = jobZkLock.TryLock()
		//defer jobZkLock.Unlock()
		if err != nil {

			result.StartTime = time.Now()
			result.Err = err
			result.EndTime = time.Now()
		} else {
			result.StartTime = time.Now()
			//执行exec
			cmd = exec.CommandContext(executeInfo.Cancel, G_Config.ExecPath, "-c", executeInfo.Job.CronExpr)
			//我们需要将任务结果返回给Scheduler，然后从ExecutingTable中删除执行记录，这样下一次才能继续调用
			output, err = cmd.CombinedOutput()
			result.EndTime = time.Now()
			result.Ouput = output
			result.Err = err
		}

		//将结果回传给调度器
		G_Scheduler.SendJobExecutorResult(result)

	}()
}

//初始化一个执行器
func InitExecutor() (err error) {
	G_Executor = &Executor{}
	return
}
